import { useEffect, useRef, useState } from 'react';
import { TransformOffset } from './Transform';
import {Color} from "./color.ts";

type EventType =
  | MouseEvent
  | React.MouseEvent<Element, MouseEvent>

type EventHandle = (e: EventType) => void;

interface useColorDragProps {
  offset?: TransformOffset;
  color?: Color;
  containerRef: React.RefObject<HTMLDivElement>;
  targetRef: React.RefObject<HTMLDivElement>;
  direction?: 'x' | 'y';
  onDragChange?: (offset: TransformOffset) => void;
  calculate?: () => TransformOffset;
}

function useColorDrag(
  props: useColorDragProps,
): [TransformOffset, EventHandle] {
  const {
    offset,
    color,
    targetRef,
    containerRef,
    direction,
    onDragChange,
    calculate,
  } = props;

  // 保存 offset
  const [offsetValue, setOffsetValue] = useState(offset || { x: 0, y: 0 });
  // 保存是否在拖动中的标记
  const dragRef = useRef({
    flag: false
  });

  useEffect(() => {
    if (dragRef.current.flag === false) {
      const calcOffset = calculate?.();
      if (calcOffset) {
        setOffsetValue(calcOffset);
      }
    }
  }, [color]);

  // 先把之前的事件监听器移除
  useEffect(() => {
    document.removeEventListener('mousemove', onDragMove);
    document.removeEventListener('mouseup', onDragStop);
  }, []);

  const updateOffset: EventHandle = e => {

    const scrollXOffset = document.documentElement.scrollLeft || document.body.scrollLeft;
    const scrollYOffset = document.documentElement.scrollTop || document.body.scrollTop;

    // e.pageY e.pageX 距离页面顶部和左边的距离
    // 减去 scrollLeft 和 scrollTop 之后就是离可视区域顶部和左边的距离
    const pageX = e.pageX - scrollXOffset;
    const pageY = e.pageY - scrollYOffset;

    const {
      x: rectX,
      y: rectY,
      width,
      height
    } = containerRef.current!.getBoundingClientRect();

    const {
      width: targetWidth,
      height: targetHeight
    } = targetRef.current!.getBoundingClientRect();

    const centerOffsetX = targetWidth / 2;
    const centerOffsetY = targetHeight / 2;

    const offsetX = Math.max(0, Math.min(pageX - rectX, width)) - centerOffsetX;
    const offsetY = Math.max(0, Math.min(pageY - rectY, height)) - centerOffsetY;

    const calcOffset = {
      x: offsetX,
      y: direction === 'x' ? offsetValue.y : offsetY,
    };

    setOffsetValue(calcOffset);
    onDragChange?.(calcOffset);
  };


  // mouseup 的时候去掉事件监听器
  const onDragStop: EventHandle = e => {
    document.removeEventListener('mousemove', onDragMove);
    document.removeEventListener('mouseup', onDragStop);

    dragRef.current.flag = false;
  };

  // mousemove 的时候根据 event 修改 offset
  const onDragMove: EventHandle = e => {
    e.preventDefault();
    updateOffset(e);
  };

  // 在 mousedown 的时候绑定 mousemove 和 mouseup 事件
  const onDragStart: EventHandle = e => {
    document.addEventListener('mousemove', onDragMove);
    document.addEventListener('mouseup', onDragStop);

    dragRef.current.flag = true;
  };

  return [offsetValue, onDragStart];
}

export default useColorDrag;
